﻿using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Linq;
using System.Linq.Expressions;
using Systematize.Data.EntityFramework.Context;
using Systematize.Domain.Data;
using Systematize.Domain.Entities;

namespace Systematize.Data.EntityFramework
{
    public class Repository<T> : IRepository<T>
        where T : Entity
    {
        protected readonly IDbContext _dbContext;
        private IDbSet<T> _entities;

        protected IDbSet<T> Entities
        {
            get { return _entities ?? (_entities = _dbContext.Set<T>()); }
        }

        public Repository(IDbContext dbContext)
        {
            _dbContext = dbContext;
        }

        public int Count()
        {
            return Entities.Count();
        }

        public int Count(Expression<Func<T, bool>> predicate)
        {
            return Entities.Count(predicate);
        }

        public IEnumerable<T> GetAll()
        {
            return Entities.ToList();
        }

        public T Find(Expression<Func<T, bool>> predicate)
        {
            return Entities.FirstOrDefault(predicate);
        }

        public IEnumerable<T> FindAll(Expression<Func<T, bool>> predicate)
        {
            return Entities.Where(predicate).ToList();
        }

        public void Insert(T entity)
        {
            if (entity == null) throw new ArgumentNullException("entity");

            Entities.Add(entity);

            _dbContext.SaveChanges();
        }

        public void Update(T entity)
        {
            if (entity == null) throw new ArgumentNullException("entity");

            var entry = _dbContext.Entry(entity);
            if (entry.State == EntityState.Detached)
            {
                Entities.Attach(entity);
                entry.State = EntityState.Modified;
            }

            _dbContext.SaveChanges();
        }

        public void Delete(T entity)
        {
            if (entity == null) throw new ArgumentNullException("entity");

            Entities.Remove(entity);

            _dbContext.SaveChanges();
        }
    }
}
